package com.xhwl.data.service.impl.devplatform;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.xhwl.common.constant.cent.message.MessageConstant;
import com.xhwl.common.dto.cent.sdata.AccountDTO;
import com.xhwl.common.dto.cent.sdata.PermissionGroupDTO;
import com.xhwl.common.dto.cent.sdata.devplatform.DeveloperDTO;
import com.xhwl.common.enums.CodeEnum;
import com.xhwl.common.enums.config.InitializeEnum;
import com.xhwl.common.enums.config.InitializeRoleEnum;
import com.xhwl.common.enums.sdata.AccountTypeEnum;
import com.xhwl.common.enums.sdata.DevelopStatusEnum;
import com.xhwl.common.enums.sdata.DevelopTypeEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.exception.DataException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.sdata.*;
import com.xhwl.common.pojo.cent.sdata.devplatform.Developer;
import com.xhwl.common.pojo.msg.NoticeData;
import com.xhwl.common.pojo.msg.Target;
import com.xhwl.common.query.cent.sdata.devplatform.DeveloperQuery;
import com.xhwl.data.dao.devplatform.IDeveloperDao;
import com.xhwl.data.service.*;
import com.xhwl.data.service.devplatform.IDeveloperService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: luyi
 * @Description:
 * @Date: Create in 15:16 2022/6/21
 */
@Slf4j
@Service
public class DeveloperServiceImpl extends ServiceImpl<IDeveloperDao, Developer> implements IDeveloperService {

    @Autowired
    private IDeveloperDao developerDao;

    @Autowired
    private IAccountService accountService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IIndustryService industryService;

    @Autowired
    IMessageCodeService messageCodeService;

    @Autowired
    IAccountRoleService accountRoleService;

    @Autowired
    IFileUploadRecordService fileUploadRecordService;

    @Autowired
    IMessageCentService messageCentService;

    /**
     * 开发者角色
     */
    private static final String DEVELOP_ROLE = "DEVELOPER";

    /**
     * 开发者业态 前台
     */
    private static final String DEVELOP_INDUSTRY = "devweb";

    /**
     * 注册成为开发者前，租户名称及社会统一信用代码组合需要做审批中校验，还需分别做唯一性校验
     * @param code 租户名
     * @param creditCode 社会统一信用代码
     * @return
     */
    @Override
    public ResultJson checkDeveloper(String code, String creditCode) {
        if (StringUtils.isEmpty(code)) {
            throw new DataException("租户名必填");
        }
        QueryWrapper<Developer> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("code", code);
        List<Developer> developers = developerDao.selectList(queryWrapper1);
        if(CollectionUtils.isEmpty(developers)){
            return ResultJson.success();
        }
        for (Developer developer : developers) {
            if(DevelopStatusEnum.CHECKING.id.equals(developer.getStatus())){
                return ResultJson.fail("当前企业的注册信息正在审核中，审核结果将通过短信通知到您注册的主账号手机，请注意查收");
            }
        }
        return ResultJson.fail("已存在");
    }

    /**
     * 注册成为开发者前，企业名称、信用代码需要做是否在审批中校验
     * @param creditCode 信用代码
     * @return
     */
    @Override
    public ResultJson checkEnterprise(String creditCode) {
        QueryWrapper<Developer> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("credit_code",creditCode);
        List<Developer> developers = developerDao.selectList(queryWrapper1);
        if(CollectionUtils.isEmpty(developers)){
            return ResultJson.success();
        }
        for (Developer developer : developers) {
            if (DevelopStatusEnum.CHECKING.id.equals(developer.getStatus())){
                return ResultJson.fail("当前企业的注册信息正在审核中，审核结果将通过短信通知到您注册的主账号手机，请注意查收");
            }
        }
        log.info("企业信息已存在");
        return ResultJson.fail("当前企业的注册信息已存在");
    }

    @Override
    @Transactional
    public ResultJson registerDeveloper(DeveloperDTO developer) {

        ResultJson resultJson = check(developer);
        if(!resultJson.getState()){
            return resultJson;
        }
        developer.setStatus(DevelopStatusEnum.CHECKING.id);
        developer.setLoginName(developer.getAccountDTO().getLoginName());
        developer.setType(DevelopTypeEnum.COMMON.id);
        developerDao.insert(developer);
        // 创建账号 设为禁用状态
        Integer accountId = createAccountBan(developer);
        developer.setAccountId(accountId);
        developerDao.updateById(developer);
        try {
            fileUploadRecordService.setStatus(developer.getBusinessLicense(), (short) 2);
        } catch (Exception e){
            e.printStackTrace();
        }
        return ResultJson.success();
    }

    /**
     * 创建禁用账号
     * @param developer
     */
    private Integer createAccountBan(DeveloperDTO developer) {
        AccountDTO accountDTO = developer.getAccountDTO();
        Account account = new Account();
        BeanUtils.copyProperties(accountDTO, account);
        // 设置为禁用
        account.setStatus((short)0);
        account.setDevelopId(developer.getId());
        account.setType(AccountTypeEnum.IAM.id);
        account.setCertification(false);
        if(StringUtils.isEmpty(account.getName())){
            account.setName(UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10));
        }
        ResultJson<Integer> resultJson = accountService.createAccount(account, null, null, null);
        if(!resultJson.getState()){
            throw new DataException(resultJson.getMessage());
        }
        return resultJson.getResult();
    }

    /**
     * 开发者审核
     * @param developerDTO
     * @return
     */
    @Transactional
    public ResultJson auditDeveloper(DeveloperDTO developerDTO, Integer industryId) {
        Developer developer = getById(developerDTO.getId());
        if(null == developer){
            return ResultJson.fail("开发者不存在");
        }
        developer.setStatus(developerDTO.getStatus());
        Account account = accountService.findById(developer.getAccountId());
        boolean isPass = DevelopStatusEnum.APPROVAL.id.equals(developerDTO.getStatus());
        if (isPass) {
            log.info("审核通过");
            // 审核通过状态改为启用中
            developer.setStatus(DevelopStatusEnum.USING.id);
            if(null == developerDTO.getAccountDTO() || CollectionUtils.isEmpty(developerDTO.getAccountDTO().getRoleIds())){
                return ResultJson.fail("缺少角色信息");
            }
            // 验证角色是否有效
            List<Role> roles = roleService.listByIds(developerDTO.getAccountDTO().getRoleIds());
            if(roles.isEmpty()){
                return ResultJson.fail("缺少角色信息");
            }
            List<Integer> roleIds = roles.stream().map(i -> i.getId()).collect(Collectors.toList());
            // 默认设置禁用，点击启用按钮后再启用
            account.setStatus((short) 1);
            account.setDevelopId(developer.getId());
            PermissionGroupDTO permissionGroup = new PermissionGroupDTO();
            permissionGroup.setRoleList(roleIds);
            AccountRelation accountRelation = new AccountRelation();
            accountRelation.setRoleIds(roleIds);
            accountService.updateAccountAdminV2(null, account, accountRelation, Arrays.asList(permissionGroup));
        }else{
            log.info("审核不通过");
        }

        developerDao.updateById(developer);

        // 短信通知开发者审核结果(buz_parameter_configbuz_parameter_config表配置)
        try {
            Integer templateId = messageCodeService.getMsgTemplateId(null, String.valueOf(industryId), null);
            sendMessage(templateId, account.getPhone(), isPass? (short)1 : (short)2);
        }catch (Exception e){
            log.error(e.getMessage());
        }
        return ResultJson.success();
    }

    @Override
    public Developer getDefault() {
        QueryWrapper<Developer> developerQueryWrapper = new QueryWrapper<>();
        developerQueryWrapper.eq("type", DevelopTypeEnum.DEFAULT.id);
        return developerDao.selectOne(developerQueryWrapper);
    }

    /**
     * 发送短信通知
     * @param templateId
     * @param phone
     * @param type 1 审核通过短信 2 审核不通过短信
     */
    private void sendMessage(Integer templateId, String phone, Short type){
        ResultJson sendResult;
        NoticeData noticeData = new NoticeData();
        noticeData.setTemplateId(templateId);
        if(1 == type){
            noticeData.setContent("您好，您的企业开发者注册申请审核已通过。欢迎加入星启开放平台，你可以使用主账号登录平台，开始您的开发之旅。");
        }else if(2 == type){
            noticeData.setContent("您好，您的企业开发者注册申请审核已未通过，建议您联系我方工作人员咨询处理。");
        }else{
            log.error("错误的类型");
            return ;
        }
        Target target = new Target();
        target.setReceivers(Arrays.asList(phone));
        sendResult = messageCentService.send(templateId, noticeData, target);
        log.info("消息中台发送短信结果={}", sendResult.getMessage());
        if (!CodeEnum.SUCCESS.getCode().equals(sendResult.getCode())) {
            throw new BusinessException("短信发送失败");
        }
    }

    /**
     * 获取开发者业态
     * @return
     */
    private Short getIndustryId() {
        Integer industryId = industryService.findIdByType(DEVELOP_INDUSTRY);
        if (null == industryId) {
            throw new DataException("缺少业态信息");
        }
        return industryId.shortValue();
    }

    private ResultJson check(DeveloperDTO developer){
        if(StringUtils.isEmpty(developer.getCode()) || 50 < developer.getCode().length()){
            return ResultJson.fail("租户编码错误");
        }
        if(StringUtils.isEmpty(developer.getEnterpriseName()) || 50 < developer.getEnterpriseName().length()){
            return ResultJson.fail("企业名称错误");
        }
        if(StringUtils.isEmpty(developer.getCreditCode()) || 18 != developer.getCreditCode().length()){
            return ResultJson.fail("社会统一信用代码错误");
        }
        if(StringUtils.isEmpty(developer.getCorporator()) || 20 < developer.getCorporator().length()){
            return ResultJson.fail("法人代表错误");
        }
        if(StringUtils.isEmpty(developer.getContacts()) || 20 < developer.getContacts().length()){
            return ResultJson.fail("缺少联系人");
        }
        if(StringUtils.isEmpty(developer.getContactsPhone())){
            return ResultJson.fail("联系电话错误");
        }
        if(StringUtils.isEmpty(developer.getBusinessLicense())){
            return ResultJson.fail("缺号营业执照");
        }
        if(null == developer.getAccountDTO()){
            return ResultJson.fail("缺少账号信息");
        }
        // 编码重复校验
        QueryWrapper<Developer> developerQueryWrapper = new QueryWrapper<>();
        if(null == developer.getId()){
            // 新增
            developerQueryWrapper.eq("code", developer.getCode());
            List<Developer> developers = developerDao.selectList(developerQueryWrapper);
            if(!CollectionUtils.isEmpty(developers)){
                return ResultJson.fail("编码重复");
            }
        }else{
            // 修改
            developerQueryWrapper.eq("code", developer.getCode());
            developerQueryWrapper.ne("id", developer.getId());
            List<Developer> developers = developerDao.selectList(developerQueryWrapper);
            if(!CollectionUtils.isEmpty(developers)){
                return ResultJson.fail("编码重复");
            }
        }
        return ResultJson.success();
    }

    @Override
    public Page<DeveloperDTO> page(DeveloperQuery developerQuery, Page page) {
        QueryWrapper<Developer> developerQueryWrapper = new QueryWrapper<>();
        queryHandler(developerQuery, developerQueryWrapper);
        Page<Developer> developerPage = developerDao.selectPage(page, developerQueryWrapper);
        List<Developer> developers = developerPage.getRecords();
        if (CollectionUtils.isEmpty(developers)) {
            page.setRecords(Lists.newArrayList());
            page.setSize(developerPage.getSize());
            page.setCurrent(developerPage.getCurrent());
            page.setTotal(developerPage.getTotal());
            return page;
        }
        List<Integer> accountIds = developers.stream().map(Developer::getAccountId).distinct().collect(Collectors.toList());

        QueryWrapper<AccountRole> accountRoleQueryWrapper = new QueryWrapper<>();
        if (!CollectionUtils.isEmpty(accountIds)) {
            accountRoleQueryWrapper.in("account_id", accountIds);
        }
        Map<Integer, List<AccountRole>> accountIdToRole = accountRoleService.list(accountRoleQueryWrapper).stream()
                .collect(Collectors.groupingBy(AccountRole::getAccountId));

        QueryWrapper<Role> roleQueryWrapper = new QueryWrapper<>();
        roleQueryWrapper.select("id", "name");
        roleQueryWrapper.eq("industry_id", 16);
        List<Role> list = roleService.list(roleQueryWrapper);
        Map<Integer, String> roleIdToName = list.stream().collect(Collectors.toMap(Role::getId, Role::getName));

        List<DeveloperDTO> developerDTOS = developers.stream().map(developer -> {
                    List<Integer> roleIds = accountIdToRole.getOrDefault(developer.getAccountId(), Lists.newArrayList())
                            .stream().filter(Objects::nonNull).map(AccountRole::getRoleId).distinct().collect(Collectors.toList());
                    String roleName = roleIds.stream().map(roleId -> roleIdToName.getOrDefault(roleId, ""))
                            .filter(StringUtils::isNoneBlank).collect(Collectors.joining("、"));
                    DeveloperDTO developerDTO = new DeveloperDTO(developer);
                    developerDTO.setIdentityRole(roleName);
                    return developerDTO;
                }).collect(Collectors.toList());
        
        page.setRecords(developerDTOS);
        page.setSize(developerPage.getSize());
        page.setCurrent(developerPage.getCurrent());
        page.setTotal(developerPage.getTotal());
        return page;
    }

    @Override
    public List<DeveloperDTO> list(DeveloperQuery developerQuery) {
        QueryWrapper<Developer> developerQueryWrapper = new QueryWrapper<>();
        queryHandler(developerQuery, developerQueryWrapper);
        List<Developer> developers = developerDao.selectList(developerQueryWrapper);
        List<DeveloperDTO> result = developers.stream().map(i -> {
            DeveloperDTO developerDTO = new DeveloperDTO();
            BeanUtils.copyProperties(i, developerDTO);
            return developerDTO;
        }).collect(Collectors.toList());
        return result;
    }

    @Override
    public DeveloperDTO detail(Integer id) {
        if(null == id){
            return null;
        }
        QueryWrapper<Developer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        List<Developer> developers = developerDao.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(developers)) {
            throw new DataException("不存在");
        }
        Developer developer = developers.get(0);
        DeveloperDTO developerDTO = new DeveloperDTO(developer);
        // 获取主账号信息
        if(null != developer.getAccountId()){
            Account account = accountService.findById(developer.getAccountId());
            if(null == account){
                log.error("账号 {}  不存在", developer.getAccountId());
            }else{
                AccountDTO accountDTO = new AccountDTO();
                account.setPassword("-");
                BeanUtils.copyProperties(account, accountDTO);
                developerDTO.setAccountDTO(accountDTO);
            }
        }else{
            log.error("开发者 {} 缺少主账号信息", id);
        }
        return developerDTO;
    }

    @Override
    public Developer getByCode(String code) {
        if(StringUtils.isEmpty(code)){
            return null;
        }
        QueryWrapper<Developer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code);
        List<Developer> developers = developerDao.selectList(queryWrapper);
        if(CollectionUtils.isEmpty(developers)){
            return null;
        }
        return developers.get(0);
    }

    private void queryHandler(DeveloperQuery developerQuery, QueryWrapper<Developer> developerQueryWrapper){
        // 过滤普通类型开发者账号
        developerQueryWrapper.and(query -> query.ne("type", DevelopTypeEnum.DEFAULT.id).or().isNull("type"));
        if(StringUtils.isNotEmpty(developerQuery.getCode())){
            developerQueryWrapper.like("code", developerQuery.getCode());
        }
        if(StringUtils.isNotEmpty(developerQuery.getEnterpriseName())){
            developerQueryWrapper.like("enterprise_name", developerQuery.getEnterpriseName());
        }
        if(StringUtils.isNotEmpty(developerQuery.getContact())){
            developerQueryWrapper.like("contacts", developerQuery.getContact());
        }
        if(StringUtils.isNotEmpty(developerQuery.getContactPhone())){
            developerQueryWrapper.like("contacts_phone", developerQuery.contactPhone);
        }
        if(null != developerQuery.getStatus()){
            developerQueryWrapper.eq("status", developerQuery.getStatus());
        }
        if(!CollectionUtils.isEmpty(developerQuery.getIds())){
            developerQueryWrapper.in("id", developerQuery.getIds());
        }
        if(null != developerQuery.getCreateRange()){
            if(null != developerQuery.getCreateRange().getMin()){
                developerQueryWrapper.ge("created_at", developerQuery.getCreateRange().getMin());
            }
            if(null != developerQuery.getCreateRange().getMax()){
                developerQueryWrapper.le("created_at", developerQuery.getCreateRange().getMax());
            }
        }
    }

    
}
